package com.pnnd;

import com.pnnd.utils.IntTuple;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class NdArrayObjectDesc {

    private DTypeObject type;
    private String name;
    private int typeNum;
    private int elsize;
    private String kind;
    private String typeStr;
    private String byteOrder;
    private NDArrayObjectDescField[] fields;
    private char hasObject;
    private NdArrayObjectDesc base;
    private IntTuple shape;

    public List<DTypeObject> getType() {

        if(this.type == null){
            return new ArrayList<>();
        }

        return Arrays.asList(this.type);
    }

    public String getName() {
        return name;
    }

    public int getTypeNum() {
        return typeNum;
    }

    public int getElsize() {
        return elsize;
    }

    public String getKind() {
        return kind;
    }

    public String getTypeStr() {
        return typeStr;
    }

    public String getByteOrder() {
        return byteOrder;
    }

    public List<NDArrayObjectDescField> getFields() {

        if(this.fields == null){
            return new ArrayList<>();
        }

        return Arrays.asList(this.fields);
    }

    public char getHasObject() {
        return hasObject;
    }

    public NdArrayObjectDesc getBase() {
        return base;
    }

    public IntTuple getShape() {
        return shape;
    }

    public static class Builder{

        private NdArrayObjectDesc desc;

        public Builder(){
            this.desc = new NdArrayObjectDesc();
        }

        public Builder setDType(DTypeObject type){
            if(type == null){
                throw new NullPointerException("type");
            }
            this.desc.type = type;
            this.desc.kind = type.getTypeStr();
            this.desc.typeNum = type.getTypeNum();
            this.desc.typeStr = type.getTypeStr();
            this.desc.elsize = type.getElementLength();
            return this;
        }

        public Builder setName(String name){
            this.desc.name = name;
            return this;
        }

        public Builder setFields(NDArrayObjectDescField ...fields){
            this.desc.fields = fields;

            return this;
        }

        public Builder setBase(NdArrayObjectDesc base) {
            this.desc.base = base;
            return this;
        }

        public Builder setShape(int ...values){
            this.desc.shape = new IntTuple(values);
            return this;
        }

        public Builder setShape(IntTuple tuple){
            this.desc.shape = tuple;
            return this;
        }

        public Builder setByteOrder(String byteOrder){
            this.desc.byteOrder = byteOrder;
            return this;
        }

        public Builder setHasObject(char hasObject){
            this.desc.hasObject = hasObject;
            return this;
        }

        public NdArrayObjectDesc build(){

            if(this.desc.fields.length != this.desc.shape.size()){
                throw new RuntimeException("fields length must equal shape size");
            }

            try{
                return this.desc;
            }finally {
                this.desc = new NdArrayObjectDesc();
            }
        }
    }
}
